from base64 import b64decode
from base64 import b64encode
import requests
import json
import time
from binascii import crc32, hexlify
from struct import calcsize, pack, unpack


CMD_PUBLIC_ID_REQ = '00'
CMD_PUBLIC_ID_ANS = '01'
CMD_INIT_REQ = '02'
CMD_INIT_ANS = '03'
CMD_POINT_REQ = '04'
CMD_POINT_ANS = '05'
CMD_UNIX_REQ = '06'
CMD_UNIX_ANS= '07'
SRV_CMD_POSITION_RESULT_REQ = '08'
SRV_CMD_POSITION_RESULT_ANS = '09'

HEADER_FORMAT = '<BB'
HEADER_SIZE = calcsize(HEADER_FORMAT)
CHECKSUM_SIZE = 1



class HttpClient:
    def __init__(self,
                 api,
                 apikey):
        self.api = api
        self.apikey = apikey

    def main_entry(self,
                   public_id,
                   tag,
                   frame= None,
                   latitude = None,
                   longitude = None,
                   height = None):
        timeout = 10
        frame = frame or b''
        params = {
            'public_id': b64encode(public_id).decode(),
            'tag': tag,
            'frame': b64encode(frame).decode(),
            'latitude': latitude,
            'longitude': longitude,
            'height': height,
        }
        print('Post body sent to server: ',json.dumps(params))
        try:
            resp = requests.post(
                url=self.api,
                json=params,
                headers={
                    'x-api-key': self.apikey
                },
                timeout=timeout
            )
            content = resp.content and resp.content.decode()
            status_code = resp.status_code
            if 200 <= status_code < 300:
                print('Response received from server: ',content)
                return json.loads(content)
            else:
                print('Bad response:',content)
        except Exception:
            print('Request timeout')
        return None

    def point_entry(self,
                   public_id,
                   tag,
                   frame= None,
                   latitude = None,
                   longitude = None,
                   height = None):
        timeout = 10
        frame = frame or b''
        params = {
            'public_id': b64encode(public_id).decode(),
            'tag': tag,
            'frame': b64encode(frame).decode(),
            'latitude': latitude,
            'longitude': longitude,
            'height': height,
        }
        print('Post body sent to server: ',json.dumps(params))
        try:
            resp = requests.post(
                url=self.api,
                json=params,
                headers={
                    'x-api-key': self.apikey
                },
                timeout=timeout
            )
            content = resp.content and resp.content.decode()
            status_code = resp.status_code
            if 200 <= status_code < 300:
                print('Response received from server: ',content)
                return json.loads(content)
            else:
                print('Bad response:',content)
                return json.loads(content)
        except Exception:
            print('Request timeout')
        return None


class SerialHeader:
    def __init__(self,tag,payload_len):
        self.tag=tag
        self.payload_len=payload_len

    @property
    def bytes(self) -> bytes:
        return pack(HEADER_FORMAT, self.tag, self.payload_len)


class SerialCommand:
    def __init__(self, header, payload):
        self.header = header
        self.payload = payload or b''
        checksum = crc32(self.header.bytes + self.payload)
        self.crc = pack('<I', checksum)[:CHECKSUM_SIZE]

    @property
    def tag(self) -> int:
        return self.header.tag

    @property
    def bytes(self) -> bytes:
        return self.header.bytes + self.payload + self.crc



def LoraServes_post(b,mac,appeui):
    url = 'http://api.easylinkin.com/api/v1/application/downlink'
    payload = {'mac': mac, 'token': 'jsyfzx123456', 'appeui': appeui, 'payload': b,
               'ttl': '2h', 'payloadType': '1'}
    resp = requests.get(url, payload)
    print('post to LoraServes', resp.json())
    print(resp.url)





